package com.rlz.lib_so;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import static com.rlz.lib_so.SoConst.TX_LIB_FF_M_PEG_3;
import static com.rlz.lib_so.SoConst.TX_LIB_SATURN_1;
import static com.rlz.lib_so.SoConst.TX_LIB_SDL_4;
import static com.rlz.lib_so.SoConst.TX_LIB_SHARED_2;
import static com.rlz.lib_so.SoConst.Type.TX_SO;
import static com.rlz.lib_so.SoDownload.SO_ZIP_PATH;

/**
 * Created by RLZ
 * on 4/19/21
 * <p>
 * 1 SO 文件的abi类型要与gradle中配置的一致
 * 2 加载时回报一个不匹配的错误 解决方法新建一个当前支持的abi文件夹 添加一个0kb的so文件
 * 3 如果加载的时候出现 not found 而逻辑没有问题说明SDK中有相互依赖的so文件 需要按照依赖顺序load
 * <p>
 * http://app.download.zhibo.tv/android/liveavso.zip
 */
public class SoLoad {


    private static LoadCallback sCallback;
    private static String sMatchName;


    /**
     * 加载 so 文件
     */
    public static void loadSoFile(@SoType String matchName, LoadCallback callback) {
        sMatchName = matchName;
        sCallback = callback;
        File dir = SoDownload.getContext().getDir("libs", Context.MODE_PRIVATE);
        if (!isLoadSoFile(dir)) {
            copy(dir.getAbsolutePath());
        } else {
            loadSo();
        }
    }

    /**
     * 判断 so 文件是否存在
     */
    public static boolean isLoadSoFile(File dir) {
        File[] currentFiles;
        currentFiles = dir.listFiles();
        boolean isLoad = false;
        if (currentFiles == null) {
            return false;
        }
        for (File currentFile : currentFiles) {
            if (currentFile.getName().contains(sMatchName)) {
                isLoad = true;
            }
        }
        return isLoad;
    }

    /**
     * 拷贝文件
     */
    private static void copy(String toFile) {

        //要复制的文件目录
        File[] currentFiles;
        File root = new File(SO_ZIP_PATH);
        if (!root.exists()) return;

        currentFiles = root.listFiles();

        File targetDir = new File(toFile);

        //创建目录
        if (!targetDir.exists()) {
            targetDir.mkdirs();
        }

        if (currentFiles == null) return;

        for (File currentFile : currentFiles) {
            if (currentFile.isDirectory()) {
                //如果当前项为子目录 进行递归
                copy(toFile + currentFile.getName() + "/");
            } else {
                //如果当前项为文件则进行文件拷贝
                if (currentFile.getName().contains(".so")) {
                    Log.e("", "当前SO ->名字" + currentFile.getName());
                    copySdcardFile(currentFile.getPath(), toFile + File.separator + currentFile.getName());
                }
            }
        }

        if (currentFiles.length > 0) loadSo();
    }

    //文件拷贝
    private static void copySdcardFile(String fromFile, String toFile) {
        try {
            FileInputStream fileFrom = new FileInputStream(fromFile);
            FileOutputStream fileTo = new FileOutputStream(toFile);
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = fileFrom.read(buffer)) != -1)
                byteStream.write(buffer, 0, len);

            fileTo.write(byteStream.toByteArray());

            byteStream.close();
            fileTo.close();
            fileFrom.close();
        } catch (Exception ex) {
            Log.e("", "file copy error   " + ex.getMessage());
            if (sCallback != null)
                sCallback.onFailed();
        }
    }


    private static void loadSo() {
        load();

        if (sCallback != null) sCallback.onSuccess();
    }


    @SuppressLint("UnsafeDynamicallyLoadedCode")
    private static void load() {
        File dir = SoDownload.getContext().getDir("libs", Context.MODE_PRIVATE);
        File[] currentFiles = dir.listFiles();
        if (currentFiles != null && currentFiles.length > 0) {

            //如果当前类型是腾讯的 需要对so进行优先级加载
            if (TextUtils.equals(sMatchName, TX_SO)) {
                loadFixed(dir.getAbsolutePath(), TX_LIB_SATURN_1);
                loadFixed(dir.getAbsolutePath(), TX_LIB_SHARED_2);
                loadFixed(dir.getAbsolutePath(), TX_LIB_FF_M_PEG_3);
                loadFixed(dir.getAbsolutePath(), TX_LIB_SDL_4);
            }

            for (File currentFile : currentFiles)
                try {
                    System.load(currentFile.getAbsolutePath());
                } catch (Error | Exception error) {
                    Log.d("NativeLoad", "load tx_lib : " + error.getMessage());
                }
            Log.e("", "加载的SO 个数 ->" + currentFiles.length);
        }
    }

    @SuppressLint("UnsafeDynamicallyLoadedCode")
    private static void loadFixed(String dirPath, String soName) {
        try {
            System.load(dirPath + File.separator + soName + ".so");
        } catch (Exception e) {
            Log.d("NativeLoad", "load lib : " + e.getMessage());
        }
    }

    public interface LoadCallback {
        void onSuccess();

        default void onFailed() {
        }
    }
}

